add insert_child_anchor signal, bug #50245
authorHavoc Pennington <hp@redhat.com>
Mon, 19 Feb 2001 23:27:27 +0000 (23:27 +0000)
committerHavoc Pennington <hp@src.gnome.org>
Mon, 19 Feb 2001 23:27:27 +0000 (23:27 +0000)
2001-02-19  Havoc Pennington  <hp@redhat.com>

* gtk/gtktextbuffer.h (struct _GtkTextBufferClass): add
insert_child_anchor signal, bug #50245

* gtk/gtktextbtree.c (_gtk_text_btree_insert_child_anchor): change
from create_child_anchor, so the anchor is passed in

* gtk/gtktextchild.c (gtk_text_child_anchor_new): new function
(_gtk_widget_segment_new): have the child anchor object passed in,
instead of creating it.

* gtk/gtktextbuffer.c (gtk_text_buffer_modified): rename
to gtk_text_buffer_get_modified

16 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/gtktextbtree.c
gtk/gtktextbtree.h
gtk/gtktextbuffer.c
gtk/gtktextbuffer.h
gtk/gtktextchild.c
gtk/gtktextchild.h
gtk/gtktextchildprivate.h
gtk/testtext.c
tests/testtext.c

index 6d5414893efe022e5e21197ccdbf2d54bffe66ee..cd8426e5e22dfa16125d1ce51fb534afccb92e08 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2001-02-19  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextbuffer.h (struct _GtkTextBufferClass): add
+       insert_child_anchor signal, bug #50245
+
+       * gtk/gtktextbtree.c (_gtk_text_btree_insert_child_anchor): change
+       from create_child_anchor, so the anchor is passed in
+
+       * gtk/gtktextchild.c (gtk_text_child_anchor_new): new function
+       (_gtk_widget_segment_new): have the child anchor object passed in, 
+       instead of creating it.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_modified): rename
+       to gtk_text_buffer_get_modified
+
 2001-02-19  Havoc Pennington  <hp@redhat.com>
 
        * gtk/gtktreemodel.c (gtk_tree_model_get_valist): hmm, someone
index 6d5414893efe022e5e21197ccdbf2d54bffe66ee..cd8426e5e22dfa16125d1ce51fb534afccb92e08 100644 (file)
@@ -1,3 +1,18 @@
+2001-02-19  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextbuffer.h (struct _GtkTextBufferClass): add
+       insert_child_anchor signal, bug #50245
+
+       * gtk/gtktextbtree.c (_gtk_text_btree_insert_child_anchor): change
+       from create_child_anchor, so the anchor is passed in
+
+       * gtk/gtktextchild.c (gtk_text_child_anchor_new): new function
+       (_gtk_widget_segment_new): have the child anchor object passed in, 
+       instead of creating it.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_modified): rename
+       to gtk_text_buffer_get_modified
+
 2001-02-19  Havoc Pennington  <hp@redhat.com>
 
        * gtk/gtktreemodel.c (gtk_tree_model_get_valist): hmm, someone
index 6d5414893efe022e5e21197ccdbf2d54bffe66ee..cd8426e5e22dfa16125d1ce51fb534afccb92e08 100644 (file)
@@ -1,3 +1,18 @@
+2001-02-19  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextbuffer.h (struct _GtkTextBufferClass): add
+       insert_child_anchor signal, bug #50245
+
+       * gtk/gtktextbtree.c (_gtk_text_btree_insert_child_anchor): change
+       from create_child_anchor, so the anchor is passed in
+
+       * gtk/gtktextchild.c (gtk_text_child_anchor_new): new function
+       (_gtk_widget_segment_new): have the child anchor object passed in, 
+       instead of creating it.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_modified): rename
+       to gtk_text_buffer_get_modified
+
 2001-02-19  Havoc Pennington  <hp@redhat.com>
 
        * gtk/gtktreemodel.c (gtk_tree_model_get_valist): hmm, someone
index 6d5414893efe022e5e21197ccdbf2d54bffe66ee..cd8426e5e22dfa16125d1ce51fb534afccb92e08 100644 (file)
@@ -1,3 +1,18 @@
+2001-02-19  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextbuffer.h (struct _GtkTextBufferClass): add
+       insert_child_anchor signal, bug #50245
+
+       * gtk/gtktextbtree.c (_gtk_text_btree_insert_child_anchor): change
+       from create_child_anchor, so the anchor is passed in
+
+       * gtk/gtktextchild.c (gtk_text_child_anchor_new): new function
+       (_gtk_widget_segment_new): have the child anchor object passed in, 
+       instead of creating it.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_modified): rename
+       to gtk_text_buffer_get_modified
+
 2001-02-19  Havoc Pennington  <hp@redhat.com>
 
        * gtk/gtktreemodel.c (gtk_tree_model_get_valist): hmm, someone
index 6d5414893efe022e5e21197ccdbf2d54bffe66ee..cd8426e5e22dfa16125d1ce51fb534afccb92e08 100644 (file)
@@ -1,3 +1,18 @@
+2001-02-19  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextbuffer.h (struct _GtkTextBufferClass): add
+       insert_child_anchor signal, bug #50245
+
+       * gtk/gtktextbtree.c (_gtk_text_btree_insert_child_anchor): change
+       from create_child_anchor, so the anchor is passed in
+
+       * gtk/gtktextchild.c (gtk_text_child_anchor_new): new function
+       (_gtk_widget_segment_new): have the child anchor object passed in, 
+       instead of creating it.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_modified): rename
+       to gtk_text_buffer_get_modified
+
 2001-02-19  Havoc Pennington  <hp@redhat.com>
 
        * gtk/gtktreemodel.c (gtk_tree_model_get_valist): hmm, someone
index 6d5414893efe022e5e21197ccdbf2d54bffe66ee..cd8426e5e22dfa16125d1ce51fb534afccb92e08 100644 (file)
@@ -1,3 +1,18 @@
+2001-02-19  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextbuffer.h (struct _GtkTextBufferClass): add
+       insert_child_anchor signal, bug #50245
+
+       * gtk/gtktextbtree.c (_gtk_text_btree_insert_child_anchor): change
+       from create_child_anchor, so the anchor is passed in
+
+       * gtk/gtktextchild.c (gtk_text_child_anchor_new): new function
+       (_gtk_widget_segment_new): have the child anchor object passed in, 
+       instead of creating it.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_modified): rename
+       to gtk_text_buffer_get_modified
+
 2001-02-19  Havoc Pennington  <hp@redhat.com>
 
        * gtk/gtktreemodel.c (gtk_tree_model_get_valist): hmm, someone
index 6d5414893efe022e5e21197ccdbf2d54bffe66ee..cd8426e5e22dfa16125d1ce51fb534afccb92e08 100644 (file)
@@ -1,3 +1,18 @@
+2001-02-19  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextbuffer.h (struct _GtkTextBufferClass): add
+       insert_child_anchor signal, bug #50245
+
+       * gtk/gtktextbtree.c (_gtk_text_btree_insert_child_anchor): change
+       from create_child_anchor, so the anchor is passed in
+
+       * gtk/gtktextchild.c (gtk_text_child_anchor_new): new function
+       (_gtk_widget_segment_new): have the child anchor object passed in, 
+       instead of creating it.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_modified): rename
+       to gtk_text_buffer_get_modified
+
 2001-02-19  Havoc Pennington  <hp@redhat.com>
 
        * gtk/gtktreemodel.c (gtk_tree_model_get_valist): hmm, someone
index 205b0aac7c1b716e6322e3a646b750099217c536..601ab8a942bb50176a97ccd75daa1be3d5b7d678 100644 (file)
@@ -1125,13 +1125,20 @@ _gtk_text_btree_insert_pixbuf (GtkTextIter *iter,
   insert_pixbuf_or_widget_segment (iter, seg);
 }
 
-GtkTextChildAnchor*
-_gtk_text_btree_create_child_anchor (GtkTextIter *iter)
+void
+_gtk_text_btree_insert_child_anchor (GtkTextIter        *iter,
+                                     GtkTextChildAnchor *anchor)
 {
   GtkTextLineSegment *seg;
   GtkTextBTree *tree;
+
+  if (anchor->segment != NULL)
+    {
+      g_warning (G_STRLOC": Same child anchor can't be inserted twice");
+      return;
+    }
   
-  seg = _gtk_widget_segment_new ();
+  seg = _gtk_widget_segment_new (anchor);
 
   tree = seg->body.child.tree = _gtk_text_iter_get_btree (iter);
   
@@ -1143,8 +1150,6 @@ _gtk_text_btree_create_child_anchor (GtkTextIter *iter)
   g_hash_table_insert (tree->child_anchor_table,
                        seg->body.child.obj,
                        seg->body.child.obj);
-  
-  return seg->body.child.obj;
 }
 
 void
index 17fd0a540b0bcc9f6f422546e957fa3b90f43eb9..723746d94f504dc68137161ca680e4f64b55c97a 100644 (file)
@@ -34,7 +34,8 @@ void _gtk_text_btree_insert        (GtkTextIter *iter,
 void _gtk_text_btree_insert_pixbuf (GtkTextIter *iter,
                                     GdkPixbuf   *pixbuf);
 
-GtkTextChildAnchor* _gtk_text_btree_create_child_anchor (GtkTextIter *iter);
+void _gtk_text_btree_insert_child_anchor (GtkTextIter        *iter,
+                                          GtkTextChildAnchor *anchor);
 
 void _gtk_text_btree_unregister_child_anchor (GtkTextChildAnchor *anchor);
 
index 6b09e25257f9256380203c06e0fe1ae33adf16ec..7bab69c6798ed464c87fc7d2eaee950911e52f75 100644 (file)
@@ -49,6 +49,7 @@ struct _ClipboardRequest
 enum {
   INSERT_TEXT,
   INSERT_PIXBUF,
+  INSERT_CHILD_ANCHOR,
   DELETE_RANGE,
   CHANGED,
   MODIFIED_CHANGED,
@@ -87,6 +88,9 @@ static void gtk_text_buffer_real_insert_text           (GtkTextBuffer     *buffe
 static void gtk_text_buffer_real_insert_pixbuf         (GtkTextBuffer     *buffer,
                                                         GtkTextIter       *iter,
                                                         GdkPixbuf         *pixbuf);
+static void gtk_text_buffer_real_insert_anchor         (GtkTextBuffer     *buffer,
+                                                        GtkTextIter       *iter,
+                                                        GtkTextChildAnchor *anchor);
 static void gtk_text_buffer_real_delete_range          (GtkTextBuffer     *buffer,
                                                         GtkTextIter       *start,
                                                         GtkTextIter       *end);
@@ -184,6 +188,22 @@ gtk_text_buffer_class_init (GtkTextBufferClass *klass)
 #endif
                    GTK_TYPE_POINTER,
                    GDK_TYPE_PIXBUF);
+
+  signals[INSERT_CHILD_ANCHOR] =
+    g_signal_newc ("insert_child_anchor",
+                   G_TYPE_FROM_CLASS (object_class),
+                   G_SIGNAL_RUN_LAST,
+                   G_STRUCT_OFFSET (GtkTextBufferClass, insert_child_anchor),
+                   NULL,
+                   gtk_marshal_VOID__BOXED_OBJECT,
+                   GTK_TYPE_NONE,
+                   2,
+#if 0
+                   /* FIXME */
+                   GTK_TYPE_TEXT_ITER,
+#endif
+                   GTK_TYPE_POINTER,
+                   GTK_TYPE_TEXT_CHILD_ANCHOR);
   
   signals[DELETE_RANGE] =
     g_signal_newc ("delete_range",
@@ -1427,6 +1447,63 @@ gtk_text_buffer_insert_pixbuf         (GtkTextBuffer      *buffer,
  * Child anchor
  */
 
+
+static void
+gtk_text_buffer_real_insert_anchor (GtkTextBuffer      *buffer,
+                                    GtkTextIter        *iter,
+                                    GtkTextChildAnchor *anchor)
+{
+  _gtk_text_btree_insert_child_anchor (iter, anchor);
+
+  g_signal_emit (G_OBJECT (buffer), signals[CHANGED], 0);
+}
+
+/**
+ * gtk_text_buffer_insert_child_anchor:
+ * @buffer: a #GtkTextBuffer
+ * @iter: location to insert the anchor
+ * @anchor: a #GtkTextChildAnchor
+ *
+ * Inserts a child widget anchor into the text buffer at @iter. The
+ * anchor will be counted as one character in character counts, and
+ * when obtaining the buffer contents as a string, will be represented
+ * by the Unicode "object replacement character" 0xFFFC. Note that the
+ * "slice" variants for obtaining portions of the buffer as a string
+ * include this character for pixbufs, but the "text" variants do
+ * not. e.g. see gtk_text_buffer_get_slice() and
+ * gtk_text_buffer_get_text(). Consider
+ * gtk_text_buffer_create_child_anchor() as a more convenient
+ * alternative to this function. The buffer will add a reference to
+ * the anchor, so you can unref it after insertion.
+ * 
+ **/
+void
+gtk_text_buffer_insert_child_anchor (GtkTextBuffer      *buffer,
+                                     GtkTextIter        *iter,
+                                     GtkTextChildAnchor *anchor)
+{
+  GtkTextChildAnchor *anchor;
+  
+  g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
+  g_return_val_if_fail (iter != NULL, NULL);
+  g_return_val_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor), NULL);
+  
+  g_signal_emit (G_OBJECT (buffer), signals[INSERT_CHILD_ANCHOR], 0,
+                 iter, anchor);
+}
+
+
+/**
+ * gtk_text_buffer_create_child_anchor:
+ * @buffer: a #GtkTextBuffer
+ * @iter: location in the buffer
+ * 
+ * This is a convenience function which simply creates a child anchor
+ * with gtk_text_child_anchor_new() and inserts it into the buffer
+ * with gtk_text_buffer_insert_child_anchor().
+ * 
+ * Return value: the created child anchor
+ **/
 GtkTextChildAnchor*
 gtk_text_buffer_create_child_anchor (GtkTextBuffer *buffer,
                                      GtkTextIter   *iter)
@@ -1436,16 +1513,15 @@ gtk_text_buffer_create_child_anchor (GtkTextBuffer *buffer,
   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
   g_return_val_if_fail (iter != NULL, NULL);
 
-  anchor = _gtk_text_btree_create_child_anchor (iter);
+  anchor = gtk_text_child_anchor_new ();
 
-  /* FIXME child-anchor-specific signal */
-  
-  gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
+  gtk_text_buffer_insert_child_anchor (buffer, iter, anchor);
+
+  g_object_unref (G_OBJECT (anchor));
 
   return anchor;
 }
 
-
 /*
  * Mark manipulation
  */
@@ -2180,7 +2256,7 @@ gtk_text_buffer_get_bounds (GtkTextBuffer *buffer,
  */
 
 /**
- * gtk_text_buffer_modified:
+ * gtk_text_buffer_get_modified:
  * @buffer: a #GtkTextBuffer 
  * 
  * Indicates whether the buffer has been modified since the last call
@@ -2191,7 +2267,7 @@ gtk_text_buffer_get_bounds (GtkTextBuffer *buffer,
  * Return value: %TRUE if the buffer has been modified
  **/
 gboolean
-gtk_text_buffer_modified (GtkTextBuffer      *buffer)
+gtk_text_buffer_get_modified (GtkTextBuffer *buffer)
 {
   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
 
index af00330cf72480b276e94f0648449f1eca2c97dd..85e42d08aa39df9aac0646ca83a5a88cc7f283f9 100644 (file)
@@ -85,14 +85,9 @@ struct _GtkTextBufferClass
                             GtkTextIter   *pos,
                             GdkPixbuf     *pixbuf);
 
-#if 0
-  /* FIXME To do this, first have to implement the sequence
-   * gtk_text_child_anchor_new(); gtk_text_buffer_insert_child_anchor();
-   */
-  void (* insert_child_anchor)   (GtkTextBuffer *buffer,
-                                  GtkTextIter   *pos,
+  void (* insert_child_anchor)   (GtkTextBuffer      *buffer,
+                                  GtkTextIter        *pos,
                                   GtkTextChildAnchor *anchor);
-#endif
   
   void (* delete_range)     (GtkTextBuffer *buffer,
                              GtkTextIter   *start,
@@ -217,7 +212,12 @@ void gtk_text_buffer_insert_pixbuf         (GtkTextBuffer *buffer,
                                             GtkTextIter   *iter,
                                             GdkPixbuf     *pixbuf);
 
-/* Create a child anchor */
+/* Insert a child anchor */
+void               gtk_text_buffer_insert_child_anchor (GtkTextBuffer      *buffer,
+                                                        GtkTextIter        *iter,
+                                                        GtkTextChildAnchor *anchor);
+
+/* Convenience, create and insert a child anchor */
 GtkTextChildAnchor *gtk_text_buffer_create_child_anchor (GtkTextBuffer *buffer,
                                                          GtkTextIter   *iter);
 
@@ -313,7 +313,7 @@ void gtk_text_buffer_get_iter_at_child_anchor (GtkTextBuffer      *buffer,
    flag, but if you would like them to you can connect a handler to
    the tag/mark signals and call set_modified in your handler */
 
-gboolean        gtk_text_buffer_modified                (GtkTextBuffer *buffer);
+gboolean        gtk_text_buffer_get_modified            (GtkTextBuffer *buffer);
 void            gtk_text_buffer_set_modified            (GtkTextBuffer *buffer,
                                                          gboolean       setting);
 
index ee0537e4a2664adf43094a64d8a6ae8b0eb94bec..6c573b7568f54f0cc5bca33d6b1858c00db3dde4 100644 (file)
@@ -199,7 +199,7 @@ GtkTextLineSegmentClass gtk_text_child_type = {
         + sizeof (GtkTextChildBody)))
 
 GtkTextLineSegment *
-_gtk_widget_segment_new (void)
+_gtk_widget_segment_new (GtkTextChildAnchor *anchor)
 {
   GtkTextLineSegment *seg;
 
@@ -214,12 +214,14 @@ _gtk_widget_segment_new (void)
                         */
   seg->char_count = 1;
 
-  seg->body.child.obj = g_object_new (GTK_TYPE_TEXT_CHILD_ANCHOR, NULL);
+  seg->body.child.obj = anchor;
   seg->body.child.obj->segment = seg;
   seg->body.child.widgets = NULL;
   seg->body.child.tree = NULL;
   seg->body.child.line = NULL;
 
+  g_object_ref (G_OBJECT (anchor));
+  
   return seg;
 }
 
@@ -331,6 +333,13 @@ gtk_text_child_anchor_class_init (GtkTextChildAnchorClass *klass)
   object_class->finalize = gtk_text_child_anchor_finalize;
 }
 
+GtkTextChildAnchor*
+gtk_text_child_anchor_new (void)
+{
+  return GTK_TEXT_CHILD_ANCHOR (g_object_new (GTK_TYPE_TEXT_CHILD_ANCHOR,
+                                              NULL));
+}
+
 static void
 gtk_text_child_anchor_finalize (GObject *obj)
 {
index 0b10c91ab0aef0e81b71960e0ae70cd373758968..1b7bd853c3566a6798cf084bd8cf89b7e8c6f044 100644 (file)
@@ -64,6 +64,8 @@ struct _GtkTextChildAnchorClass
 
 GType gtk_text_child_anchor_get_type (void) G_GNUC_CONST;
 
+GtkTextChildAnchor* gtk_text_child_anchor_new (void);
+
 GList*   gtk_text_child_anchor_get_widgets (GtkTextChildAnchor *anchor);
 gboolean gtk_text_child_anchor_get_deleted (GtkTextChildAnchor *anchor);
 
index 24bb908e4cee63d32619d8a040a823d77d2d6189..70ce11344e3023a09c535e1a76394f32c4e3b9dc 100644 (file)
@@ -75,7 +75,7 @@ struct _GtkTextChildBody
   GtkTextLine *line;
 };
 
-GtkTextLineSegment *_gtk_widget_segment_new      (void);
+GtkTextLineSegment *_gtk_widget_segment_new      (GtkTextChildAnchor *anchor);
 void                _gtk_widget_segment_add      (GtkTextLineSegment *widget_segment,
                                                   GtkWidget          *child);
 void                _gtk_widget_segment_remove   (GtkTextLineSegment *widget_segment,
index 292681e2befca4b73f3ee10d74467bad2d679d9b..1969589f121bc131aa28131126d6bac1d46ab795 100644 (file)
@@ -429,7 +429,6 @@ fill_example_buffer (GtkTextBuffer *buffer)
   GdkPixbuf *pixbuf;
   int i;
   char *str;
-  GtkTextChildAnchor *anchor;
   
   /* FIXME this is broken if called twice on a buffer, since
    * we try to create tags a second time.
@@ -510,7 +509,7 @@ fill_example_buffer (GtkTextBuffer *buffer)
                 "direction", GTK_TEXT_DIR_RTL,
                 "indent", 30,
                 "left_margin", 20,
-                  "right_margin", 20,
+                "right_margin", 20,
                 NULL);
 
 
@@ -693,7 +692,7 @@ static View *
 get_empty_view (View *view)
 {
   if (!view->buffer->filename &&
-      !gtk_text_buffer_modified (view->buffer->buffer))
+      !gtk_text_buffer_get_modified (view->buffer->buffer))
     return view;
   else
     return create_view (create_buffer ());
@@ -1366,7 +1365,7 @@ save_as_buffer (Buffer *buffer)
 static gboolean
 check_buffer_saved (Buffer *buffer)
 {
-  if (gtk_text_buffer_modified (buffer->buffer))
+  if (gtk_text_buffer_get_modified (buffer->buffer))
     {
       char *pretty_name = buffer_pretty_name (buffer);
       char *msg = g_strdup_printf ("Save changes to '%s'?", pretty_name);
index 292681e2befca4b73f3ee10d74467bad2d679d9b..1969589f121bc131aa28131126d6bac1d46ab795 100644 (file)
@@ -429,7 +429,6 @@ fill_example_buffer (GtkTextBuffer *buffer)
   GdkPixbuf *pixbuf;
   int i;
   char *str;
-  GtkTextChildAnchor *anchor;
   
   /* FIXME this is broken if called twice on a buffer, since
    * we try to create tags a second time.
@@ -510,7 +509,7 @@ fill_example_buffer (GtkTextBuffer *buffer)
                 "direction", GTK_TEXT_DIR_RTL,
                 "indent", 30,
                 "left_margin", 20,
-                  "right_margin", 20,
+                "right_margin", 20,
                 NULL);
 
 
@@ -693,7 +692,7 @@ static View *
 get_empty_view (View *view)
 {
   if (!view->buffer->filename &&
-      !gtk_text_buffer_modified (view->buffer->buffer))
+      !gtk_text_buffer_get_modified (view->buffer->buffer))
     return view;
   else
     return create_view (create_buffer ());
@@ -1366,7 +1365,7 @@ save_as_buffer (Buffer *buffer)
 static gboolean
 check_buffer_saved (Buffer *buffer)
 {
-  if (gtk_text_buffer_modified (buffer->buffer))
+  if (gtk_text_buffer_get_modified (buffer->buffer))
     {
       char *pretty_name = buffer_pretty_name (buffer);
       char *msg = g_strdup_printf ("Save changes to '%s'?", pretty_name);